const fs = require("fs")
const esprima = require("esprima")
const estraverse = require("estraverse")
const escodegen = require("escodegen")
const iconv = require("iconv-lite");
const CryptoJS = require("crypto-js")
const {get_file,get_rand_names} = require("../tools/utils")


function MapStr(map) {
    var obj = {};
    var c = 0;
    for (var [key, value] of map) {
        obj[key] = value;
        c += 1;
    }
    var jsonString = JSON.stringify(obj);
    console.log(jsonString);
    console.log("map len:",c);
}

/*
返回 子串的数量
 */
function countSubstringSimple(str, subStr) {
    const regex = new RegExp(subStr, 'g');
    const matches = str.match(regex);
    return matches ? matches.length : 0;
}

/*
删除签名的数字
 */
function removeNumbersFromStart(str) {
    // 使用正则表达式替换字符串开头的数字
    // \d+ 匹配一个或多个数字，^ 表示字符串的开始
    return str.replace(/^\d+/, '');
}


/*
从文件路径获取ast树
 */
function get_ast_by_file(file){
    var code = get_file(file)
    var ast = esprima.parse(code);
    return ast;
}

/*
从字符串获取ast树
 */
function getAstByString(code){
    var ast = esprima.parse(code);
    return ast;
}

//获取初始化的所有变量，存放在列表里
//返回一个列表
function store_local_declare(ast){
    var result = [];
    estraverse.traverse(ast,{
        enter(node, parent){
            if(node.type==="Identifier"&&parent.type==="VariableDeclarator"){
                if(parent.init===null){
                    result.push(node.name);
                }
            }
        }
    })
    return result;
}

// 存储所有的变量值，初始化的变量值--如果重复赋值可能会有问题.
// 返回一个字典
function store_local_init(ast){
    var result = new Map();;
    estraverse.traverse(ast,{
        enter:function (node){
            if(node.type==="AssignmentExpression" && node.operator==="="&&node.left.type==="Identifier"){
                if(node.right.type==="Literal"){
                    result.set(node.left.name, node.right.value);
                }
            }
        }
    })
    return result;
}

/*
將var_locals中定义的固定的变量 在引用使用的地方替换掉
var_locals = map对象
 */
function identifier_tool(ast, var_locals){
    estraverse.replace(ast, {
        enter:(node, parent)=>{
            if(node.type==="Identifier" && var_locals.has(node.name)){
                if(!(parent.type==="VariableDeclarator"&&parent.id&&parent.id===node)&&!(parent.type==="AssignmentExpression"&&parent.left&&parent.left===node)){
                    return{
                        type:esprima.Syntax.Literal,
                        value:var_locals.get(node.name),
                        raw:var_locals.get(node.name).toString(),
                    }
                }
            }
        }
    });
}

/*
删除固定的变量, 未使用的变量(因为已经进行了变量替换)
var a;
a = 1;
var_dict = map(){"a":1}
 */
function delete_vars(ast, var_dict){
    estraverse.replace(ast,{
        enter(node,parent){
            if(node.type==="VariableDeclaration"&&node.declarations&&node.declarations.length===1){
                var node1 = node.declarations[0];
                if(node1.type==="VariableDeclarator"&&node1.id&&node1.id.type==="Identifier"){
                    if(var_dict.has(node1.id.name)){
                        return estraverse.VisitorOption.Remove;
                    }
                }
            }
            if(node.type==="ExpressionStatement"&&node.expression&&node.expression.type==="AssignmentExpression"){
                if(node.expression.left&&node.expression.left.type==="Identifier"&&node.expression.right&&node.expression.right.type==="Literal"){
                    if(var_dict.has(node.expression.left.name)){
                        return estraverse.VisitorOption.Remove;
                    }
                }
            }
            if(node.type==="AssignmentExpression"&&node.left){
                if(var_dict.has(node.left.name)){
                    return estraverse.VisitorOption.Remove;
                }
            }
        }
    })
}

/*
找到所有var_locals 里面定义的变量 初始化的地方并执行
 */
function identifier_tool2(ast, js_code){
    var result = new Map();
    var js_ast = esprima.parse(js_code);
    var var_locals = store_local_declare(js_ast);
    eval(js_code);
    console.log(var_locals+"");
    estraverse.replace(ast,{
        enter(node, parent){
            if(node.type==="Identifier"&&var_locals.includes(node.name)){
                if(parent.type==="AssignmentExpression"&&parent.operator==="="&&parent.left===node){
                    var code = escodegen.generate(parent.right);
                    console.log(code);
                    var val = eval(code);
                    result.set(node.name, val);
                    console.log(val);
                    eval(escodegen.generate(parent));
                    parent.right = {
                        type:esprima.Syntax.Literal,
                        value:val,
                        raw:val.toString()
                    }
                }
            }
        }
    })
    return result;
}

/*
判断node节点的所有元素是否都是 Literal 常量
 */
function isLiteralArray(node){
    for(let i=0;i<node.length;i++){
        var item = node[i];
        if(item.type!=="Literal"){
            return false;
        }
    }
    return true
}

//处理常量表达式计算 比如 var a = 1+2; a = 1-3; 3元运算符固定值替换
function binary_tool(ast){
    estraverse.replace(ast,{
        leave(node,parent){
            // "a"+"b"  1+2
            if(node.type==="BinaryExpression"&&node.left.type==="Literal"&&node.right.type==="Literal"){
                try{
                    var code = escodegen.generate(node);
                    console.log(code);
                    var val = eval(code);
                    console.log(val);
                    if(val===undefined){
                        return {
                            type:esprima.Syntax.Identifier,
                            name:"undefined"
                        }
                    }
                    return {
                        type:esprima.Syntax.Literal,
                        value:val,
                        raw:val.toString()
                    }
                }catch (e){
                    console.log(e);
                }
            }
            // [1]+[0]
            if(node.type==="BinaryExpression"&&node.left.type==="ArrayExpression"&&node.right.type==="ArrayExpression"){
                if(isLiteralArray(node.left.elements)){
                    if(isLiteralArray(node.right.elements)){
                        try{
                            var code = escodegen.generate(node);
                            console.log(code);
                            var val = eval(code);
                            console.log(val);
                            if(val===undefined){
                                return {
                                    type:esprima.Syntax.Identifier,
                                    name:"undefined"
                                }
                            }
                            return {
                                type:esprima.Syntax.Literal,
                                value:val,
                                raw:val.toString()
                            }
                        }catch (e){
                            console.log(e);
                        }
                    }
                }
            }
            //"1" +[]
            if(node.type==="BinaryExpression"&&node.left.type==="Literal"&&node.right.type==="ArrayExpression"){
                if(isLiteralArray(node.right.elements)){
                    try{
                        var code = escodegen.generate(node);
                        console.log(code);
                        var val = eval(code);
                        console.log(val);
                        if(val===undefined){
                            return {
                                type:esprima.Syntax.Identifier,
                                name:"undefined"
                            }
                        }
                        return {
                            type:esprima.Syntax.Literal,
                            value:val,
                            raw:val.toString()
                        }
                    }catch (e){
                        console.log(e);
                    }
                }
            }
            //[]+"1"
            if(node.type==="BinaryExpression"&&node.left.type==="ArrayExpression"&&node.right.type==="Literal"){
                if(isLiteralArray(node.left.elements)){
                    try{
                        var code = escodegen.generate(node);
                        console.log(code);
                        var val = eval(code);
                        console.log(val);
                        if(val===undefined){
                            return {
                                type:esprima.Syntax.Identifier,
                                name:"undefined"
                            }
                        }
                        return {
                            type:esprima.Syntax.Literal,
                            value:val,
                            raw:val.toString()
                        }
                    }catch (e){
                        console.log(e);
                    }
                }
            }

            //+[]
            if(node.type==="UnaryExpression"&&node.argument&&node.argument.type==="ArrayExpression"&&node.operator!=="-"){
                if(node.argument.elements.length===0){
                    try{
                        var code = escodegen.generate(node);
                        console.log(code);
                        var val = eval(code);
                        console.log(val);
                        if(val===undefined){
                            return {
                                type:esprima.Syntax.Identifier,
                                name:"undefined"
                            }
                        }
                        return {
                            type:esprima.Syntax.Literal,
                            value:val,
                            raw:val.toString()
                            // raw:(val!==null) ? val.toString(),
                        }
                    }catch (e){
                        console.log(e);
                    }
                }
            }
            //!1  +1
            if(node.type==="UnaryExpression"&&node.argument&&node.argument.type==="Literal"&&node.operator!=="-"){
                try{
                    var code = escodegen.generate(node);
                    console.log(code);
                    var val = eval(code);
                    console.log(val);
                    if(val===undefined){
                        return {
                            type:esprima.Syntax.Identifier,
                            name:"undefined"
                        }
                    }
                    return {
                        type:esprima.Syntax.Literal,
                        value:val,
                        raw:val.toString()
                    }
                }catch (e){
                    console.log(e);
                }
            }
            // a = true?1:0;
            if(node.type==="ConditionalExpression"&&node.test&&node.consequent&&node.alternate){
                if(node.test.type==="Literal"){
                    var code = escodegen.generate(node.test);
                    var val = eval(code);
                    if(val){
                        return node.consequent;
                    }else{
                        return node.alternate;
                    }
                }
            }
        }
    })
}

//计算出t3 的值并修改语句, 返回每个case之间的联系
//该函数只适合于条件值更改的单条语句
function switchcase_tool(ast, discrim){
    var result = [];
    let switchDepth = 0;
    let skipLeave = false;
    estraverse.replace(ast,{
        enter(node,parent){
            if(node.type==="SwitchStatement"){

                // if(node.discriminant.name!==discrim){
                //     return estraverse.VisitorOption.Skip;
                // }
                switchDepth++;
                if (switchDepth > 1) {
                    skipLeave = true;
                    return estraverse.VisitorOption.Skip;
                }

                this.currentDiscriminant = node.discriminant.name;
            }
            if (node.type === 'SwitchCase') {
                if(node.test!==null){
                    // 当前 case 语句上下文
                    if(node.test.value!==undefined&&node.test.value!==null){
                        this.currentCaseTest = node.test.value;
                        //记录是否存在赋值语句。如果没有那么就是结束块

                        // this.is_next_case = false;
                    }
                    this.is_end = true;

                }
            }
            if (this.currentDiscriminant===discrim&&this.currentCaseTest!==undefined){

                if(node.type==="AssignmentExpression"){
                    if(node.left.name===discrim){
                        this.is_next_case = true;
                        // var t3 = this.currentCaseTest;
                        var code = "var " + discrim + " = " + this.currentCaseTest+";\n";
                        var val = eval(code+escodegen.generate(node))
                        node.operator = "=";
                        node.right.value = val;
                        node.right.raw = val.toString();
                        result.push([this.currentCaseTest, val]);
                        this.is_end = false;
                    }
                }
            }
        },
        leave(node){
            if(skipLeave){
                skipLeave = false;
                return
            }
            if(node.type==="SwitchStatement"){
                this.currentDiscriminant = null;
                // switchDepth--;
            }
            if (node.type === 'SwitchCase'){
                if(this.is_end){
                    result.push([this.currentCaseTest])
                    if(this.currentCaseTest==null){
                        console.log(escodegen.generate(node));
                    }
                    console.log("结束块 :"+this.currentCaseTest);
                }

                // if(!this.is_next_case){
                //     result.push([this.currentCaseTest])
                //     // this.is_next_case = true
                // }
                this.currentCaseTest = null;
            }
            //离开的时候 没有发现下一个case块
            // if(!this.is_next_case){
            //     result.push([this.currentCaseTest])
            //     // this.is_next_case = true
            // }
        }
    })
    console.log(result);
    //[ 128, 103 ], [ 690, 345 ], [ 8, 744 ],   [ 313, 680 ], [ 735, 570 ],...
    return result;
}

/*
根据test的值获取case语句块的代码
 */
function get_by_discrim(ast, test_value){
    var des_node = null;
    let switchDepth = 0;
    estraverse.traverse(ast,{
        enter(node,parent){
            if(node.type==="SwitchStatement"){
                switchDepth++;
                if (switchDepth > 1) {
                    return estraverse.VisitorOption.Skip;
                }
            }
            if (node.type === 'SwitchCase') {
                if(node.test!==null){
                    // 当前 case 语句上下文
                    currentCaseTest = node.test.value;
                    if(currentCaseTest===test_value){
                        des_node = escodegen.generate(node.consequent[0]);
                        if (des_node.startsWith('{') && des_node.endsWith('}')) {
                            des_node = des_node.substring(1, des_node.length - 1).trim();
                        }
                        return estraverse.VisitorOption.Break;
                    }
                }else if(test_value===null){
                    des_node = escodegen.generate(node.consequent[0]);
                    // if (des_node.startsWith('{') && des_node.endsWith('}')) {
                    //     des_node = des_node.substring(1, des_node.length - 1).trim();
                    // }
                    return estraverse.VisitorOption.Break;
                }

            }
        },
        leave(node, parent){
            if(node.type==="SwitchStatement"){
                switchDepth--;
            }
        }
    })
    return des_node;
}

/*
先获取所有的变量引用
var _0x5aabf6 = a1_0x2141;
 */
function get_all_reference_var(ast, vars_name){
    var result = new Array();
    estraverse.traverse(ast,{
        enter(node,parent){
            if(node.type==="Identifier"&&parent.type==="VariableDeclarator"){
                if(parent.id!==undefined){
                    if(vars_name.includes(node.name)){
                        if(!result.includes(parent.id.name)){
                            result.push(parent.id.name);
                        }

                    }
                }
            }
        }
    })
    return result;
}

/*
函数变量替换 将 多个变量赋值替换为原值
比如
function a1_0x2141(_0x1bd596, _0x2ea66a){}
var _0x5aabf6 = a1_0x2141;
_0x5aabf6(1)
该函数目前没用了
 */
function var_exchange(file, save_file, func_name){
    var ast = get_ast_by_file(file);
    // 有可能有很多嵌套的引用，需要多计算几次.
    var refs = get_all_reference_var(ast,[func_name]);
    var refs = get_all_reference_var(ast,refs);
    var refs = get_all_reference_var(ast,refs);
    var refs = get_all_reference_var(ast,refs);
    var refs = get_all_reference_var(ast,refs);
    console.log(refs);
    estraverse.replace(ast,{
        enter(node, parent){
            if(node.type==="Identifier"&&parent.type==="CallExpression"){
                if(refs.includes(node.name)){
                    console.log(node.name);
                    return {
                        type:esprima.Syntax.Identifier,
                        name:func_name,
                    }
                }
            }
        }
    })
    var new_code = escodegen.generate(ast);
    fs.writeFile(save_file, new_code, (err) => {
    });
}

/*
把字符串保存到文件中
 */
function save_to_file(code, save_file){
    fs.writeFile(save_file, code, (err) => {
    });
}

function getCodeByAst(ast){
    return escodegen.generate(ast);
}

function save_ast_to_file(ast, save_file){
    var new_code = escodegen.generate(ast);
    save_to_file(new_code,save_file);
}

/*
逗号表达式拆分
var a=1,b=2,c=3; =>
var a=1;
var b=2;
var c=3;
 */
function sequence_split(ast){
    estraverse.replace(ast,{
        enter(node,parent){
            if(node.type==="VariableDeclaration"&&node.declarations&&node.declarations.length>1&&node.kind&&node.kind==="var"){
                const newDeclarations = node.declarations.map(declarator => ({
                    type: 'VariableDeclaration',
                    declarations: [declarator],
                    kind: node.kind
                }));
                if (parent.type === 'BlockStatement' || parent.type === 'Program') {
                    const index = parent.body.indexOf(node);
                    parent.body.splice(index, 1, ...newDeclarations);
                }
            }
            if(node.type==="ExpressionStatement"&&node.expression&&node.expression.type==="SequenceExpression"){
                const newDeclarations = node.expression.expressions.map(expr=>({
                    type: 'ExpressionStatement',
                    expression: expr
                }));
                if (parent.type === 'BlockStatement'|| parent.type === 'Program') {
                    const index = parent.body.indexOf(node);
                    parent.body.splice(index, 1, ...newDeclarations);
                }
            }
            if (node.type === 'ReturnStatement' && node.argument && node.argument.type === 'SequenceExpression') {
                const expressions = node.argument.expressions;

                // 将SequenceExpression的每个子表达式转换为ExpressionStatement
                const newStatements = expressions.slice(0, -1).map(expr => ({
                    type: 'ExpressionStatement',
                    expression: expr
                }));

                // 最后的表达式用于新的return语句
                const lastExpression = expressions[expressions.length - 1];
                const returnStatement = {
                    type: 'ReturnStatement',
                    argument: lastExpression
                };

                // 将新的语句插入到parent的body中
                if (parent.type === 'BlockStatement') {
                    const index = parent.body.indexOf(node);
                    parent.body.splice(index, 1, ...newStatements, returnStatement);
                }

            }
        }
    })
}

function get_sample_func_map(){
    var unary_operator_dict = {
        "-":"Opposite",
        "void":"VoidVar",
        "~":"bitwise_not",
        "!":"logical_neg"
    }
    var binary_operator_dict = {
        "<":"is_lt",
        "<=":"is_lte",
        ">":"is_lg",
        ">=":"is_lge",
        "===":"is_eq_strict",
        "==":"is_eq_nostrict",
        "!==":"is_ueq_strict",
        "!=":"is_ueq_nostrict",
        "instanceof":"is_instanceof",
        ">>":"right_shift",
        "<<":"left_shift",
        "charCodeAt":"CharCodeAt1",
        "toString":"ToString1",
        "indexOf":"IndexOf1",
        "length":"Length1",
        "in":"is_in",
        "*":"mul",
        "+":"add",
        "-":"sub",
        "/":"div",
        "substr":"Substr1",
        "|":"bitwise_or",
        "%":"mod",
        "&":"bitwise_and",
        "^":"bitwise_eor",
    }

// 创建一个新的 Map 对象
    const map = new Map();

// 遍历对象的属性并添加到 Map 中
    for (const [key, value] of Object.entries(unary_operator_dict)) {
        map.set(value, 1);
    }

    for (const [key, value] of Object.entries(binary_operator_dict)) {
        map.set(value, 1);
    }
    return map;
}

function get_sample_func(ast){
    var unary_operator_dict = {
        "-":"Opposite",
        "void":"VoidVar",
        "~":"bitwise_not",
        "!":"logical_neg"
    }
    var binary_operator_dict = {
        "<":"is_lt",
        "<=":"is_lte",
        ">":"is_lg",
        ">=":"is_lge",
        "===":"is_eq_strict",
        "==":"is_eq_nostrict",
        "!==":"is_ueq_strict",
        "!=":"is_ueq_nostrict",
        "instanceof":"is_instanceof",
        ">>":"right_shift",
        "<<":"left_shift",
        "charCodeAt":"CharCodeAt1",
        "toString":"ToString1",
        "indexOf":"IndexOf1",
        "length":"Length1",
        "in":"is_in",
        "*":"mul",
        "+":"add",
        "-":"sub",
        "/":"div",
        "substr":"Substr1",
        "|":"bitwise_or",
        "%":"mod",
        "&":"bitwise_and",
        "^":"bitwise_eor",
    }
    var result = new Map();
    estraverse.traverse(ast,{
        enter(node, parent){
            if(node.type==="FunctionExpression"&&parent.type==="VariableDeclarator"){
                if(node.body&&node.body.type==="BlockStatement"){
                    if(node.body.body&&node.body.body.length===1){
                        var node1 = node.body.body[0];
                        if(node1.type==="ReturnStatement"){
                            if(node1.argument){
                                if(node1.argument.type==="UnaryExpression"&&node1.argument.argument.type==="Identifier"){
                                    var opera = node1.argument.operator;
                                    if(opera in unary_operator_dict){
                                        result.set(parent.id.name, unary_operator_dict[opera]);
                                    }
                                }
                                if(node1.argument.type==="BinaryExpression"){
                                    var opera = node1.argument.operator;
                                    if(opera in binary_operator_dict&&node1.argument.left.type==="Identifier"&&node1.argument.right.type==="Identifier"){
                                        result.set(parent.id.name, binary_operator_dict[opera]);
                                    }
                                }
                                if(node1.argument.type==="CallExpression"&&node1.argument.callee){
                                    var code = escodegen.generate(node1);
                                    console.log(code);
                                    if(node1.argument.callee.property&&node1.argument.callee.property.name in binary_operator_dict){
                                        result.set(parent.id.name, binary_operator_dict[node1.argument.callee.property.name]);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            if(parent&&parent.type==="FunctionDeclaration"&&node.type==="BlockStatement"){
                if(node.body&&node.body.length===1){
                    var node1 = node.body[0];
                    if(node1.type==="ReturnStatement"){
                        if(node1.argument){
                            if(node1.argument){
                                if(node1.argument.type==="UnaryExpression"){
                                    var opera = node1.argument.operator;
                                    if(opera in unary_operator_dict){
                                        result.set(parent.id.name, unary_operator_dict[opera]);
                                    }
                                }
                                if(node1.argument.type==="BinaryExpression"&&node1.argument.left.type==="Identifier"&&node1.argument.right.type==="Identifier"){
                                    var opera = node1.argument.operator;
                                    if(opera in binary_operator_dict){
                                        result.set(parent.id.name, binary_operator_dict[opera]);
                                    }
                                }
                                if(node1.argument.type==="CallExpression"&&node1.argument.callee){
                                    var code = escodegen.generate(node1);
                                    console.log(code);
                                    if(node1.argument.callee.property&&node1.argument.callee.property.name in binary_operator_dict){
                                        result.set(parent.id.name, binary_operator_dict[node1.argument.callee.property.name]);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    })
    // console.log("result:"+JSON.stringify(result));
    console.log("result:"+result);
    return result;
}

/*
处理函数重命名 -- 对一些简单的函数 对其函数名重新命名
 */
function rechange_funcname(ast){
    var func_obj = get_sample_func(ast);
    estraverse.replace(ast, {
        enter(node, parent){
            if(node.type==="Identifier"&&func_obj.has(node.name)){
                node.name = func_obj.get(node.name);
            }
        }
    });
}

/*
处理变量重命名
{"vCn":"sensor_arg2","fOn":"sensor_arg4","W8n":"sensor_arg6","jCn":"sensor_arg8","V8n":"sensor_arg10","Y8n":"sensor_arg12","sOn":"sensor_arg14","zCn":"sensor_arg16","KOn":"sensor_arg18","R8n":"sensor_arg20","tOn":"sensor_arg22","hCn":"sensor_arg24","qln":"sensor_arg26","MCn":"sensor_arg28","IOn":"sensor_arg30","UJn":"sensor_arg32","QJn":"sensor_arg34","gJn":"sensor_arg36","pJn":"sensor_arg38","TOn":"sensor_arg40","MJn":"sensor_arg42","qJn":"sensor_arg44","FOn":"sensor_arg46","COn":"sensor_arg48","fJn":"sensor_arg52","j8n":"sensor_arg54","lOn":"sensor_arg56","cCn":"sensor_arr"}
根据map一一替换
 */
function rename_vars(ast, var_map){
    estraverse.replace(ast, {
        enter(node, parent){
            if(node.type==="Identifier"&&var_map.has(node.name)){
                node.name = var_map.get(node.name);
            }
        }
    })
}

/*
对一些常量值进行重命名
常量函数重命名
该函数只是查找
重命名操作交给 rename_vars 函数进行
 */
function ConstReturn(ast){
    var result = new Map();
    estraverse.traverse(ast, {
        enter(node, parent){
            if(node.type==="AssignmentExpression"){
                if(node.right&&node.right.type==="ArrayExpression"&&node.right.elements){
                    var nodes = node.right.elements;
                    var LiteralCount = 0;
                    for(let i=0;i<nodes.length;i++){
                        var nodei = nodes[i];
                        if(nodei.type==="Literal"){
                            LiteralCount++;
                        }else if(nodei.type==="UnaryExpression"&&nodei.argument&&nodei.argument.type==="Literal"){
                            LiteralCount++;
                        }
                    }
                    if(LiteralCount>0&&LiteralCount===nodes.length){
                        var code = escodegen.generate(node);
                        console.log(code);
                        if(node.left&&node.left.name&&node.left.name.length<=3){
                            // var code = escodegen.generate(node);
                            // console.log(code);
                            result.set(node.left.name, `ConstArr${LiteralCount}${node.left.name}`);
                        }
                    }
                }
            }
            if(node.type==="VariableDeclarator"&&node.init&&node.init.type==="ArrayExpression"){
                var nodes = node.init.elements;
                var LiteralCount = 0;
                for(let i=0;i<nodes.length;i++){
                    var nodei = nodes[i];
                    if(nodei.type==="Literal"){
                        LiteralCount++;
                    }else if(nodei.type==="UnaryExpression"&&nodei.argument&&nodei.argument.type==="Literal"){
                        LiteralCount++;
                    }
                }
                // console.log("LiteralCount:"+LiteralCount);
                if(LiteralCount>0&&LiteralCount===nodes.length){
                    if(node.id&&node.id.name.length<=3){
                        // var code = escodegen.generate(node);
                        // console.log(code);
                        result.set(node.id.name, `ConstArr${LiteralCount}${node.id.name}`);
                    }
                }
            }
            if(node.type==="VariableDeclarator"&&node.id&&node.init&&node.init.type==="FunctionExpression"){
                if(node.init.body&&node.init.body.type==="BlockStatement"&&node.init.body.body&&node.init.body.body.length===1){
                    var node1 = node.init.body.body[0];
                    if(node1.type==="ReturnStatement"&&node1.argument&&node1.argument.type==="ArrayExpression"&&node1.argument.elements){
                        var nodes = node1.argument.elements;
                        var LiteralCount = 0;
                        for(let i=0;i<nodes.length;i++){
                            var nodei = nodes[i];
                            if(nodei.type==="Literal"){
                                LiteralCount++;
                            }else if(nodei.type==="UnaryExpression"&&nodei.argument&&nodei.argument.type==="Literal"){
                                LiteralCount++;
                            }
                        }
                        if(LiteralCount>0&&LiteralCount===nodes.length){
                            // var code = escodegen.generate(node);
                            // console.log(code);
                            if(node.id.name.length<=3){
                                result.set(node.id.name, `GetConstArr${LiteralCount}${node.id.name}`);
                            }

                        }
                    }
                }
            }
            if(node.type==="FunctionDeclaration"&&node.id&&node.body&&node.body.type==="BlockStatement"){
                if(node.body.body&&node.body.body.length===1){
                    var node1 = node.body.body[0];
                    if(node1.type==="ReturnStatement"&&node1.argument&&node1.argument.type==="ArrayExpression"&&node1.argument.elements){
                        var nodes = node1.argument.elements;
                        var LiteralCount = 0;
                        for(let i=0;i<nodes.length;i++){
                            var nodei = nodes[i];
                            if(nodei.type==="Literal"){
                                LiteralCount++;
                            }else if(nodei.type==="UnaryExpression"&&nodei.argument&&nodei.argument.type==="Literal"){
                                LiteralCount++;
                            }
                        }
                        if(LiteralCount>0&&LiteralCount===nodes.length){
                            // var code = escodegen.generate(node);
                            // console.log(code);
                            if(node.id.name.length<=3){
                                result.set(node.id.name, `GetConstArr${LiteralCount}${node.id.name}`);
                            }

                        }
                    }
                }
            }
        }
    })
    return result;
}

/*
从ast中将保存在集合 set_funcs中的函数名找出来单独存到一个文件里
 */
function parse_set_func_code(ast, set_funcs){
    let arr_funcs = [...set_funcs];
    arr_funcs.sort();

    var code = "";
    for(let i=0;i<arr_funcs.length;i++){
        var func_code = parse_func_code(ast, arr_funcs[i]);
        code += func_code;
    }
    return code;

    // var code = "";
    // estraverse.traverse(ast,{
    //     enter(node, parent){
    //         if(node.type==="VariableDeclarator"&&node.id&&node.init&&node.init.type==="FunctionExpression"){
    //             var func_name = node.id.name;
    //             if(set_funcs.has(func_name)){
    //                 code += "var "+escodegen.generate(node)+"\n";
    //             }
    //         }
    //         if(node.type==="FunctionDeclaration"&&node.id){
    //             var func_name = node.id.name;
    //             if(set_funcs.has(func_name)){
    //                 code += escodegen.generate(node)+"\n";
    //             }
    //         }
    //     }
    // });
    // return code;
}

/*
提取单个函数的代码
 */
function parse_func_code(ast, func_name){
    var code = "";
    estraverse.traverse(ast,{
        enter(node, parent){
            if(node.type==="VariableDeclarator"&&node.id&&node.init&&node.init.type==="FunctionExpression"){
                var name = node.id.name;
                if(name===func_name){
                    code += "var "+escodegen.generate(node)+"\n";
                }
            }
            if(node.type==="FunctionDeclaration"&&node.id){
                var name = node.id.name;
                if(name===func_name){
                    code += escodegen.generate(node)+"\n";
                }
            }
        }
    });
    return code;
}

/*
ast必须 就是一个函数节点对函数内部的变量按照顺序进行重命名
 */
function rename_func_vars(ast, func_name){
    var result = new Map();
    var md5_str = removeNumbersFromStart(CryptoJS.MD5(func_name).toString().toLowerCase());
    var local_prefix = "local_"+md5_str.slice(0,3);
    var argus_prefix = "arg_"+md5_str.slice(0,3);
    var func_prefix = "func_"+md5_str.slice(0,3);
    var count = 1;
    var count2 = 1;
    var count3 = 1;
    estraverse.traverse(ast,{
        enter(node, parent){
            if(node.type==="VariableDeclarator"&&node.id&&node.id.type==="Identifier"&&node.id.name!==func_name){
                if(node.id.name.length<4){
                    result.set(node.id.name, local_prefix+count);
                    count += 1;
                }
            }
            if((node.type==="FunctionDeclaration"||node.type==="FunctionExpression")&&node.params&&node.params.length>0){
                for(let i = 0;i<node.params.length;i++){
                    let nodei = node.params[i];
                    if(nodei.type==="Identifier"){
                        result.set(nodei.name, argus_prefix+count2);
                        count2 += 1;
                    }
                }
            }
            if(node.type==="CatchClause"&&node.param){
                if(node.param.type==="Identifier"){
                    result.set(node.param.name, "e");
                }
            }
            //内部的函数定义--重写命名
            if(node.type==="FunctionExpression"&&node.id&&node.id.type==="Identifier"&&node.id.name!==func_name){
                result.set(node.id.name, func_prefix+count3);
                count3 += 1
            }
        }
    });
    rename_vars(ast, result);
    // return result;
}

/*
将数组中的固定值替换到引用他们的地方
 */
function de_arr(ast, arr, arr_name){
    // var c = "{$arr}="
    estraverse.replace(ast, {
        enter(node, parent){
            if(node.type==="MemberExpression"&&node.object&&node.property){
                if(node.object.type==="Identifier"&&node.object.name===arr_name){
                    if(node.property.type==="Literal"){
                        var code = escodegen.generate(node);
                        var val = arr[node.property.value];
                        console.log(code, val);
                        return {
                            type:esprima.Syntax.Literal,
                            value:val,
                            raw:val.toString()
                        }
                    }
                }
            }
        }
    });
}



/*
把一个函数的作用域下面的所有变量找出来重命名；注意不能进入下一层的函数作用域内; 只处理当前函数
 */
function rename_var_infunc(ast, names){
    var var_maps = new Map();
    estraverse.replace(ast,{
        leave(node, parent){
            // if(node.type==="FunctionExpression"||node.type==="FunctionDeclaration"){
            //     return estraverse.VisitorOption.Skip;
            // }
            if(node.type==="VariableDeclarator" && node.id &&node.id.type==="Identifier"){
                var_maps.set(node.id.name, names.pop());
            }
            if(node.type==="FunctionExpression"||node.type==="FunctionDeclaration"){
                // if(node.id&&node.id.type==="Identifier"){
                //     var_maps.set(node.id.name, names.pop());
                // }
                if(node.params){
                    for(var i=0;i<node.params.length;i++){
                        var nodei = node.params[i];
                        if(nodei.type==="Identifier"){
                            var_maps.set(nodei.name, names.pop());
                        }
                    }
                }
            }
        }
    })
    rename_vars(ast, var_maps);
}

/*
查找ast节点中存在的重复变量定义
 */
function find_repeat_vars(ast){
    var map = new Map();
    var result = new Map();
    // var repeat_vars = [];
    estraverse.traverse(ast, {
        enter(node, parent){
            // if(node.type==="Identifier"){
            if((node.type==="FunctionExpression"||node.type==="VariableDeclarator"||node.type==="FunctionDeclaration")&&node.id){
            // if((node.type==="FunctionExpression"||node.type==="FunctionDeclaration")&&node.id){
                if(map.has(node.id.name)){
                    console.log(node.id.name);
                    // throw "找到重复值";
                    if(!result.has(node.id.name)){
                        result.set(node.id.name,"1");
                    }
                }
                map.set(node.id.name, "1");
            }

            if((node.type==="FunctionDeclaration"||node.type==="FunctionExpression")&&node.params){
                for(var i=0;i<node.params.length;i++){
                    var nodei = node.params[i];
                    if(nodei.type==="Identifier"){
                        if(map.has(nodei.name)){
                            console.log(nodei.name);
                            if(!result.has(nodei.name)){
                                result.set(nodei.name,"1");
                            }
                        }
                        map.set(nodei.name, "1");
                    }
                }
            }
            if(node.type==="CatchClause"&&node.param){
                if(map.has(node.param.name)){
                    console.log(node.param.name);
                    if(!result.has(node.param.name)){
                        result.set(node.param.name,"1");
                    }
                }
                map.set(node.param.name, "1");
            }
            if(node.type==="Property"&&node.key&&node.key.type==="Identifier"){
                if(map.has(node.key.name)){
                    console.log(node.key.name);
                    if(!result.has(node.key.name)){
                        result.set(node.key.name,"1");
                    }
                }
                map.set(node.key.name, "1");
            }
            if(node.type==="RestElement"&&node.argument&&node.argument.type==="Identifier"){
                if(map.has(node.argument.name)){
                    console.log(node.argument.name);
                    if(!result.has(node.argument.name)){
                        result.set(node.argument.name,"1");
                    }
                }
                map.set(node.argument.name, "1");
            }
        }
    });
    console.log(MapStr(result));
    return result;
}

/*
获取ast 中的所有变量
 */
function get_all_names(ast){
    var names = new Set();
    estraverse.traverse(ast,{
        enter(node, parent){
            if(node.type==="Identifier"){
                names.add(node.name);
            }
        }
    })
    return names;
}

/*
除去ast中已经使用的名称，重新生成随机的变量名
 */
function get_new_name(ast){
    var old_names = get_all_names(ast);
    var names = get_rand_names(old_names);
    return names
}

/*
实现 把一个ast节点下的变量重命名，让全局变量和局部变量名不重复。 不能用了，会有问题
 */
function rename_all_var(ast){
    var names = get_new_name(ast);
    estraverse.traverse(ast, {
        leave(node, parent){
            if(node.type==="FunctionExpression"||node.type==="FunctionDeclaration"){
                rename_var_infunc(node, names);
            }
        }
    })
}

/*

 */
function getFirstLevelFuncs(astNode){
    var functionsList = [];

    // function findFirstLevelFunctions(astNode) {
        let currentDepth = 0; // 用于跟踪函数嵌套层级

        estraverse.traverse(astNode, {
            enter: function (node) {
                // 检查是否是函数类型
                if(astNode!==node){
                    if (node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression' || node.type === 'ArrowFunctionExpression') {
                        if (currentDepth === 0) {
                            // 如果在当前作用域（深度为 0），则记录函数
                            functionsList.push(node.id ? node.id.name : '<anonymous function>');
                        }
                        // 每进入一个函数，层级加一
                        currentDepth++;
                    }
                }

            },
            leave: function (node) {
                // 每离开一个函数，层级减一
                if(astNode!==node){
                    if (node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression' || node.type === 'ArrowFunctionExpression') {
                        currentDepth--;
                    }
                }

            }
        });

        return functionsList;
    // }

}

/*
根据传递的值的类型返回不同的ast节点
 */
function getAstNodeByObj(value){
    var result;
    if(typeof value==="number"||typeof value==="string"||typeof value==="boolean"){
        result = {
            type:"Literal",
            value:value,
            raw:value.toString()
        }
    }else if(typeof value==="function"){
        result = {
            type:"Identifier",
            name:value.name,
        }
    }else if(typeof value==="object"){
        var code = "var a = " +JSON.stringify(value);
    }
    return result;
}


module.exports={
    MapStr,
    get_file,
    binary_tool,
    store_local_init,
    store_local_declare,
    identifier_tool,
    identifier_tool2,
    get_ast_by_file,
    getAstByString,
    switchcase_tool,
    get_by_discrim,
    var_exchange,
    save_ast_to_file,
    sequence_split,
    rechange_funcname,
    delete_vars,
    rename_vars,
    ConstReturn,
    countSubstringSimple,
    parse_set_func_code,
    save_to_file,
    getCodeByAst,
    rename_func_vars,
    de_arr,
    rename_all_var,
    find_repeat_vars,
    getFirstLevelFuncs,
    get_new_name,
    get_sample_func_map
}

